package main

import (
	"Learngo/mooc/tree"
	"fmt"
)

// 组合的方式去增强已有类型, 其实就是Java的保包装类
type myTreeNode struct {
	node *tree.Node
}

// 内嵌, 其实吧，这个破玩意儿就是继承，大差不差吧，换汤不换药
type innerTreeNode struct {
	*tree.Node // 内嵌（语法糖）使代码看起来更加简洁
}

// 这个会优先输出左边，在输出自己，再输出右边
func (myNode *myTreeNode) postOrder() {
	if myNode == nil || myNode.node == nil {
		return
	}
	left := myTreeNode{myNode.node.Left}
	left.postOrder()
	right := myTreeNode{myNode.node.Right}
	right.postOrder()
	myNode.node.Print()
}

func (myNode *innerTreeNode) postOrder() {
	if myNode == nil || myNode.Node == nil {
		return
	}
	left := myTreeNode{myNode.Left}
	left.postOrder()
	right := myTreeNode{myNode.Right}
	right.postOrder()
	myNode.Print()
}

// Traverse 重载方法
func (myNode *innerTreeNode) Traverse() {
	fmt.Println("This method is shadowed.")
}

func main() {
	var root = tree.Node{}
	root = tree.Node{Value: 3}
	root.Left = &tree.Node{}
	root.Right = &tree.Node{Value: 5}
	root.Right.Left = new(tree.Node)
	root.Left.Right = tree.CreateNode(2)
	root.Right.Left.SetValue(4)

	root.Traverse()

	fmt.Println()
	node := myTreeNode{&root}
	node.postOrder()

	fmt.Println()
	treeNode := innerTreeNode{&root}
	treeNode.postOrder()

	// 更进一步，直接创建内嵌的innerTreeNode，甚至后面都不需要改了
	rootInner := innerTreeNode{&tree.Node{Value: 3}}
	rootInner.Left = &tree.Node{}
	rootInner.Right = &tree.Node{Value: 5}
	rootInner.Right.Left = new(tree.Node)
	rootInner.Left.Right = tree.CreateNode(2)
	rootInner.Right.Left.SetValue(4)
	rootInner.postOrder()

	// 内嵌类调用重载方法
	rootInner.Traverse()
	// 内嵌类调用父类的重载前的方法
	rootInner.Node.Traverse()
}
